﻿using Adaptive.Agrona;
using Adaptive.Agrona.Concurrent;

using System;

using Unity.Type.BinaryType;

namespace Unity.Type
{
    public class MetadataDeserializer : IUnityDeserializer<Metadata>
    {
        private static readonly MessageHeader MessageHeader = new MessageHeader();
        private static readonly Metadata MetadataDecoder = new Metadata();

        private const int MessageLength = MessageHeader.Size + Metadata.BlockLength;
        private readonly IMutableDirectBuffer _decodeBuffer = new UnsafeBuffer(new ByteBuffer(MessageLength, 0));

        private void Wrap()
        {
            MessageHeader.Wrap(_decodeBuffer, 0, MessageHeader.EncodingSchemaVersion);
            MetadataDecoder.WrapForDecode(_decodeBuffer, MessageHeader.Size, Metadata.BlockLength, MessageHeader.Version);
        }

        private string GetUnityId()
        {
            return new string(MetadataDecoder.GetUnityId().ToCharArray());
        }

        private int GetChangerCsiId()
        {
            return MetadataDecoder.ChangerCsiId;
        }

        private EntityType GetEntityType()
        {
            return MetadataDecoder.EntityType;
        }

        private EventType GetEventType()
        {
            return MetadataDecoder.EventType;
        }

        private long GetVersion()
        {
            return MetadataDecoder.Version;
        }

        private long GetTimestamp()
        {
            return MetadataDecoder.Timestamp;
        }

        private long GetVersionDelete()
        {
            return MetadataDecoder.VersionDelete;
        }

        private int GetFormatVer()
        {
            return MetadataDecoder.FormatVer;
        }

        private Metadata InternalDeserialize()
        {
            try
            {
                Wrap();
                Metadata newMetadata = new Metadata();
                newMetadata.SetUnityId(GetUnityId());
                newMetadata.ChangerCsiId = GetChangerCsiId();
                newMetadata.EntityType = GetEntityType();
                newMetadata.EventType = GetEventType();
                newMetadata.Version = GetVersion();
                newMetadata.Timestamp = GetTimestamp();
                newMetadata.VersionDelete = GetVersionDelete();
                newMetadata.FormatVer = GetFormatVer();
                return newMetadata;
            }
            catch(Exception exception)
            {
                Console.Error.WriteLine(exception);
                return null;
            }
        }

        public Metadata Deserialize(byte[] data)
        {
            _decodeBuffer.Wrap(data);
            return InternalDeserialize();
        }
    }
}
